import numpy as np
import matplotlib.pyplot as plt
def objective(x):
    return x[0] ** 2.0

class SA:
    def __init__(self, x, bounds, n_iter, sigma, T):
        self.x = x
        self.bounds = bounds
        self.best = x[0] # init
        self.best_obj = objective([self.best])
        self.n_iter = n_iter
        self.sigma = sigma
        self.T = T
        self.cur,self.cur_obj = self.best, self.best_obj
        self.dims = len(bounds)
    def run(self):
        self.cost = []
        for i in range(self.n_iter):
            #假设候选解来自正态分布 N(self.cur, sigma)
            candidate = self.cur + np.random.randn(self.dims) * self.sigma
            candidate_obj = objective(candidate)
            #最优化参数和目标值
            if candidate_obj < self.best_obj:
                self.best, self.best_obj = candidate, candidate_obj
                self.cost.append(self.best_obj)

            #是否接受更差的解
            diff = candidate_obj - self.best_obj
            T = self.T/float(i+1)
            metropolis = np.exp(-diff/T)
            if diff < 0 and np.random.rand() < metropolis:
                self.cur, self.cur_obj = candidate, candidate_obj
        return 


if __name__ == "__main__":
    bounds = [-5,5]
    x = np.arange(bounds[0], bounds[1], 0.1)
    print(x)
    T = 10
    n_iter = 1000

    ###############################
    sa = SA(x, bounds, n_iter, sigma = 0.2, T = T)
    sa.run()
    print(sa.best)
    plt.figure()
    plt.plot(sa.cost)
    plt.show()
